home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH03 / SIMX86 / SIMX86P.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-04-09  |  56.3 KB  |  2,431 lines

  1. unit Simx86p;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, Patterns, Menus, StdCtrls, TabNotBk, ExtCtrls, VBXCtrl,
  8.   Switch, Spin, GetInput, Printers;
  9.  
  10. type
  11.  
  12.   TMem = array [0..$ffef] of byte;
  13.   TMemPtr = ^TMem;
  14.  
  15.   TSIMx86Form = class(TForm)
  16.     Simx86Pages: TTabbedNotebook;
  17.     SourceCode: TMemo;
  18.     MainMenu: TMainMenu;
  19.     File1: TMenuItem;
  20.     Edit: TMenuItem;
  21.     New: TMenuItem;
  22.     Open: TMenuItem;
  23.     Save: TMenuItem;
  24.     SaveAs: TMenuItem;
  25.     Cut: TMenuItem;
  26.     Copy: TMenuItem;
  27.     Paste: TMenuItem;
  28.     Delete: TMenuItem;
  29.     EditBreak: TMenuItem;
  30.     BeforeQuit: TMenuItem;
  31.     PrintMenuItem: TMenuItem;
  32.     SelectAll: TMenuItem;
  33.     OpenDialog: TOpenDialog;
  34.     SaveDialog: TSaveDialog;
  35.     StartAdrs: TEdit;
  36.     StartAdrsLbl: TLabel;
  37.     ASMbtn: TButton;
  38.  
  39.     Mem01: TEdit;
  40.     Mem02: TEdit;
  41.     Mem03: TEdit;
  42.     Mem04: TEdit;
  43.     Mem05: TEdit;
  44.     Mem00: TEdit;
  45.     Mem06: TEdit;
  46.     Mem07: TEdit;
  47.  
  48.     AdrsEntry: TEdit;
  49.     Label0: TLabel;
  50.     Label1: TLabel;
  51.     Label2: TLabel;
  52.     Label3: TLabel;
  53.     Label4: TLabel;
  54.     Label5: TLabel;
  55.     Label6: TLabel;
  56.     Label7: TLabel;
  57.     Lbl8: TLabel;
  58.     Lbl10: TLabel;
  59.     Lbl18: TLabel;
  60.     Lbl20: TLabel;
  61.     Lbl28: TLabel;
  62.     Lbl30: TLabel;
  63.     Lbl38: TLabel;
  64.     Mem10: TEdit;
  65.     Mem11: TEdit;
  66.     Mem12: TEdit;
  67.     Mem13: TEdit;
  68.     Mem14: TEdit;
  69.     Mem15: TEdit;
  70.     Mem16: TEdit;
  71.     Mem17: TEdit;
  72.     Mem27: TEdit;
  73.     Mem26: TEdit;
  74.     Mem25: TEdit;
  75.     Mem24: TEdit;
  76.     Mem23: TEdit;
  77.     Mem22: TEdit;
  78.     Mem21: TEdit;
  79.     Mem20: TEdit;
  80.     Mem30: TEdit;
  81.     Mem31: TEdit;
  82.     Mem32: TEdit;
  83.     Mem33: TEdit;
  84.     Mem34: TEdit;
  85.     Mem35: TEdit;
  86.     Mem36: TEdit;
  87.     Mem37: TEdit;
  88.     Mem47: TEdit;
  89.     Mem46: TEdit;
  90.     Mem45: TEdit;
  91.     Mem44: TEdit;
  92.     Mem43: TEdit;
  93.     Mem42: TEdit;
  94.     Mem41: TEdit;
  95.     Mem40: TEdit;
  96.     Mem50: TEdit;
  97.     Mem51: TEdit;
  98.     Mem52: TEdit;
  99.     Mem53: TEdit;
  100.     Mem54: TEdit;
  101.     Mem55: TEdit;
  102.     Mem56: TEdit;
  103.     Mem57: TEdit;
  104.     Mem67: TEdit;
  105.     Mem66: TEdit;
  106.     Mem65: TEdit;
  107.     Mem64: TEdit;
  108.     Mem63: TEdit;
  109.     Mem62: TEdit;
  110.     Mem61: TEdit;
  111.     Mem60: TEdit;
  112.     Mem70: TEdit;
  113.     Mem71: TEdit;
  114.     Mem72: TEdit;
  115.     Mem73: TEdit;
  116.     Mem74: TEdit;
  117.     Mem75: TEdit;
  118.     Mem76: TEdit;
  119.     Mem77: TEdit;
  120.     IntVect: TEdit;
  121.     IntVectLbl: TLabel;
  122.     ResetVectLbl: TLabel;
  123.     ResetVect: TEdit;
  124.     Label8: TLabel;
  125.     DisAsm: TListBox;
  126.     Output: TListBox;
  127.     InPort0: TBiSwitch;
  128.     InPort2: TBiSwitch;
  129.     InPort4: TBiSwitch;
  130.     InPort6: TBiSwitch;
  131.     OutPort8: TShape;
  132.     OutPortA: TShape;
  133.     OutPortC: TShape;
  134.     OutPortE: TShape;
  135.     FFF8Lbl: TLabel;
  136.     FFFALbl: TLabel;
  137.     FFFCLbl: TLabel;
  138.     FFFELbl: TLabel;
  139.     RunBtn: TButton;
  140.     StepBtn: TButton;
  141.     HaltBtn: TButton;
  142.     InterruptBtn: TButton;
  143.     OutputLbl: TLabel;
  144.     RunningLite: TPanel;
  145.     AXValue: TEdit;
  146.     AXLbl: TLabel;
  147.     BXValue: TEdit;
  148.     DXValue: TEdit;
  149.     CXValue: TEdit;
  150.     IPValue: TEdit;
  151.     BXLbl: TLabel;
  152.     CXLbl: TLabel;
  153.     DXLbl: TLabel;
  154.     IPLbl: TLabel;
  155.     Instruction: TLabel;
  156.     DisAsmAdrs: TEdit;
  157.     EqualFlag: TCheckBox;
  158.     LessThanFlag: TCheckBox;
  159.     ResetBtn: TButton;
  160.     Input: TListBox;
  161.     InputLbl: TLabel;
  162.     SpinButton: TSpinButton;
  163.     ClrMemBtn: TButton;
  164.     PrintDialog: TPrintDialog;
  165.     N1: TMenuItem;
  166.     Quit: TMenuItem;
  167.  
  168.     procedure QuitClick(Sender: TObject);
  169.     procedure CutClick(Sender: TObject);
  170.     procedure CopyClick(Sender: TObject);
  171.     procedure PasteClick(Sender: TObject);
  172.     procedure DeleteClick(Sender: TObject);
  173.     procedure SelectAllClick(Sender: TObject);
  174.     procedure NewClick(Sender: TObject);
  175.     procedure OpenClick(Sender: TObject);
  176.     procedure SaveAsClick(Sender: TObject);
  177.     procedure HexChange(Sender: TObject);
  178.     procedure FormCreate(Sender: TObject);
  179.     procedure AdrsEntryChange(Sender: TObject);
  180.     procedure StartAdrsChange(Sender: TObject);
  181.     procedure ASMbtnClick(Sender: TObject);
  182.     procedure Simx86PagesChange(Sender: TObject; NewTab: Integer;
  183.       var AllowChange: Boolean);
  184.     procedure ClrMemBtnClick(Sender: TObject);
  185.     procedure DisAsmAdrsChange(Sender: TObject);
  186.     procedure SpinButtonDownClick(Sender: TObject);
  187.     procedure SpinButtonUpClick(Sender: TObject);
  188.     procedure ResetBtnClick(Sender: TObject);
  189.     procedure RunBtnClick(Sender: TObject);
  190.     procedure HaltBtnClick(Sender: TObject);
  191.     procedure InterruptBtnClick(Sender: TObject);
  192.     procedure IntVectChange(Sender: TObject);
  193.     procedure IPValueChange(Sender: TObject);
  194.     procedure StepBtnClick(Sender: TObject);
  195.     procedure PrintMenuItemClick(Sender: TObject);
  196.     procedure SaveClick(Sender: TObject);
  197.   private
  198.     { Private declarations }
  199.   public
  200.     { Public declarations }
  201.   end;
  202.  
  203.  
  204. var
  205.   SIMx86Form: TSIMx86Form;
  206.   MemEntry: array[0..7,0..7] of TEdit;
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213. implementation
  214.  
  215. type
  216.  
  217.     TSymPtr = ^TSym;
  218.  
  219.     TSym = record
  220.              value:word;
  221.              defined:boolean;
  222.            end;
  223.  
  224.  
  225.  
  226.  
  227. const
  228.     MaxCodeAdrs = 4095;
  229.  
  230. var
  231.  
  232.   HasOpcode:Boolean;
  233.   Opcode:word;
  234.   HasReg:Boolean;
  235.   RegCode:word;
  236.   HasOperand:Boolean;
  237.   OperandCode:word;
  238.   HasValue:Boolean;
  239.   OperandValue:word;
  240.   StoreMem:boolean;
  241.  
  242.   Halted:boolean;
  243.   Running:boolean;
  244.   PendingInt:boolean;
  245.   InInt:boolean;
  246.   IntAdrs:word;
  247.  
  248.   Val:byte;
  249.  
  250.   AX: word;
  251.   BX: word;
  252.   CX: word;
  253.   DX: word;
  254.   IP: word;
  255.  
  256.   LineNum:integer;
  257.   Adrs:word;
  258.   MemAdrs:word;
  259.   MemWS:integer;
  260.   AbortAsm:Boolean;
  261.   NoError:Boolean;
  262.   Memory: TMemPtr;
  263.   SymTbl: array ['A'..'Z'] of TSym;
  264.  
  265.  
  266.   SaveAX:word;
  267.   SaveBX:word;
  268.   SaveCX:word;
  269.   SaveDX:word;
  270.   SaveIP:word;
  271.   SaveEqual:boolean;
  272.   SaveLess:boolean;
  273.  
  274.   Reg:byte;
  275.   RegMem:byte;
  276.   Operation:byte;
  277.   InstrSize:word;
  278.  
  279.   Op1:^word;
  280.   Op2v:word;
  281.   offset:word;
  282.  
  283.   Filename:string;
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291. {$F+}
  292. function ProcessLbl(Pat:TPatPtr):boolean; forward;
  293. function GetLbl(Pat:TPatPtr):boolean; forward;
  294. function ConvertHex(Pat:TPatPtr):boolean; forward;
  295.  
  296. procedure SetJmp(Pat:TPatPtr); forward;
  297. procedure SetJa(Pat:TPatPtr); forward;
  298. procedure SetJae(Pat:TPatPtr); forward;
  299. procedure SetJb(Pat:TPatPtr); forward;
  300. procedure SetJbe(Pat:TPatPtr); forward;
  301. procedure SetJe(Pat:TPatPtr); forward;
  302. procedure SetJne(Pat:TPatPtr); forward;
  303.  
  304. procedure SetNot(Pat:TPatPtr); forward;
  305. procedure SetAnd(Pat:TPatPtr); forward;
  306. procedure SetOr(Pat:TPatPtr); forward;
  307. procedure SetCmp(Pat:TPatPtr); forward;
  308. procedure SetSub(Pat:TPatPtr); forward;
  309. procedure SetAdd(Pat:TPatPtr); forward;
  310. procedure SetMovReg(Pat:TPatPtr); forward;
  311. procedure SetMovMem(Pat:TPatPtr); forward;
  312.  
  313.  
  314. procedure SetIret(Pat:TPatPtr); forward;
  315. procedure SetHalt(Pat:TPatPtr); forward;
  316. procedure SetBrk(Pat:TPatPtr); forward;
  317. procedure SetPut(Pat:TPatPtr); forward;
  318. procedure SetGet(Pat:TPatPtr); forward;
  319.  
  320. procedure SetAX(Pat:TPatPtr); forward;
  321. procedure SetBX(Pat:TPatPtr); forward;
  322. procedure SetCX(Pat:TPatPtr); forward;
  323. procedure SetDX(Pat:TPatPtr); forward;
  324.  
  325. procedure SetAX2(Pat:TPatPtr); forward;
  326. procedure SetBX2(Pat:TPatPtr); forward;
  327. procedure SetCX2(Pat:TPatPtr); forward;
  328. procedure SetDX2(Pat:TPatPtr); forward;
  329.  
  330. procedure SetBXInd(Pat:TPatPtr); forward;
  331. procedure SetBXIndx(Pat:TPatPtr); forward;
  332. procedure SetABS(Pat:TPatPtr); forward;
  333. procedure SetImm(Pat:TPatPtr); forward;
  334.  
  335.  
  336. {$F-}
  337.  
  338. const
  339.  
  340.      { WS1- Matches a string containing one or more white-   }
  341.      {      space characters.                                }
  342.  
  343.      WS1:TPattern = (mf:OneOrMoreCset; m:(cset:[' ',#9]);
  344.                      Next:NIL; Alt:NIL; Success:NIL);
  345.  
  346.      { WS0- Matches a string containing zero or more white-  }
  347.      {      space characters.                                }
  348.  
  349.      WS0:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  350.                       Next:NIL; Alt:NIL; Success:NIL);
  351.  
  352.  
  353.      { A Pattern that matches whitespace at the end of a line }
  354.  
  355.      SkipToEOS:TPattern=(mf:EOS; m:(ch:' ');
  356.                        Next:NIL; Alt:NIL; Success:NIL);
  357.  
  358.      WSeoln:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  359.                        Next:@SkipToEOS; Alt:NIL; Success:NIL);
  360.  
  361.  
  362.  
  363.      { Match an x86 register mode here.                       }
  364.  
  365.  
  366.      TryDX:Tpattern=(mf:Matchistr; m:(str:'DX');
  367.                         Next:NIL; Alt:NIL; Success:SetDX);
  368.  
  369.      TryCX:Tpattern=(mf:Matchistr; m:(str:'CX');
  370.                         Next:NIL; Alt:@TryDX; Success:SetCX);
  371.  
  372.      TryBX:Tpattern=(mf:Matchistr; m:(str:'BX');
  373.                         Next:NIL; Alt:@TryCX; Success:SetBX);
  374.  
  375.      TryReg:Tpattern=(mf:Matchistr; m:(str:'AX');
  376.                         Next:NIL; Alt:@TryBX; Success:SetAX);
  377.  
  378.  
  379.      { Match an x86 addressing mode here                     }
  380.  
  381.      TryImm:TPattern=( mf:ConvertHex; m:(ch:' ');
  382.                       Next:@WSEoln; Alt:NIL; Success:SetImm);
  383.  
  384.      TryDX2:Tpattern=(mf:Matchistr; m:(str:'DX');
  385.                         Next:@WSeoln; Alt:@TryImm; Success:SetDX2);
  386.  
  387.      TryCX2:Tpattern=(mf:Matchistr; m:(str:'CX');
  388.                         Next:@WSeoln; Alt:@TryDX2; Success:SetCX2);
  389.  
  390.      TryBX2:Tpattern=(mf:Matchistr; m:(str:'BX');
  391.                         Next:@WSeoln; Alt:@TryCX2; Success:SetBX2);
  392.  
  393.      TryReg2:Tpattern=(mf:Matchistr; m:(str:'AX');
  394.                         Next:@WSeoln; Alt:@TryBX2; Success:SetAX2);
  395.  
  396.  
  397.  
  398.      BXBrack:TPattern=( mf:MatchChar; m:(ch:']');
  399.                       Next:NIL; Alt:NIL; Success:NIL);
  400.  
  401.      BXBrackWS:TPattern=( mf:SpanCset; m:(cset:[' ',#9]);
  402.                       Next:@BXBrack; Alt:NIL; Success:NIL);
  403.  
  404.      BXEnd:TPattern=( mf:MatchiStr; m:(str:'BX');
  405.                       Next:@BXBrackWS; Alt:NIL; Success:NIL);
  406.  
  407.      TryABS:TPattern=( mf:Succeed; m:(ch:' ');
  408.                        Next:@BXBrackWS; Alt:NIL; Success:SetABS);
  409.  
  410.      BXPlus:TPattern=( mf:MatchChar; m:(ch:'+');
  411.                       Next:@BXEnd; Alt:@TryABS; Success:SetBXIndx);
  412.  
  413.      BXPlusWS:TPattern=( mf:SpanCset; m:(cset:[' ',#9]);
  414.                       Next:@BXPlus; Alt:NIL; Success:NIL);
  415.  
  416.      BXIndex:TPattern=( mf:ConvertHex; m:(ch:' ');
  417.                         Next:@BXPlusWS; Alt:@BXEnd; Success:NIL);
  418.  
  419.  
  420.      BXBracket:TPattern=( mf:MatchiStr; m:(str:'BX');
  421.                           Next:@BXBrackWS; Alt:@BXIndex; Success:SetBXInd);
  422.  
  423.  
  424.      BXIndWS:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  425.                       Next:@BXBracket; Alt:NIL; Success:NIL);
  426.  
  427.      DoMem:TPattern=( mf:MatchChar; m:(ch:'[');
  428.                       Next:@BXIndWS; Alt:@TryReg2; Success:NIL);
  429.  
  430.  
  431.      { Generic Two-operand instructions }
  432.  
  433.      TryOr:TPattern=(mf:MatchiStr; m:(str:'OR');
  434.                         Next:NIL; Alt:NIL; Success:SetOr);
  435.  
  436.      TryAnd:TPattern=(mf:MatchiStr; m:(str:'AND');
  437.                         Next:NIL; Alt:@TryOr; Success:SetAnd);
  438.  
  439.      TryCmp:TPattern=(mf:MatchiStr; m:(str:'CMP');
  440.                         Next:NIL; Alt:@TryAnd; Success:SetCmp);
  441.  
  442.      TrySub:TPattern=(mf:MatchiStr; m:(str:'SUB');
  443.                         Next:NIL; Alt:@TryCmp; Success:SetSub);
  444.  
  445.      TryAdd:TPattern=( mf:MatchiStr; m:(str:'ADD');
  446.                        Next:NIL; Alt:@TrySub; Success:SetAdd);
  447.  
  448.  
  449.  
  450.      { Handle label definitions at the beginning of the line    }
  451.  
  452.      Lbl:TPattern=(mf:ProcessLbl; m:(ch:' ');
  453.                    Next:NIL; Alt:NIL; Success:NIL);
  454.  
  455.  
  456.  
  457.      { A statement may be one of the following:                 }
  458.      {                                                          }
  459.      {       1: A Blank Line.                                   }
  460.      {       2: An optional label in column 1 followed by an    }
  461.      {          instruction.                                    }
  462.      {       3: Whitespace followed by an instruction.          }
  463.      {       4: An instruction starting in column 1.            }
  464.      {                                                          }
  465.      { The following patterns match one of the above.           }
  466.  
  467.      { Zero-Operand Instructions here: }
  468.  
  469.  
  470.      TryBrk:TPattern=( mf:MatchiStr; m:(str:'BRK');
  471.                       Next:@WSeoln; Alt:NIL; Success:SetBrk);
  472.  
  473.      TryIRet:TPattern=( mf:MatchiStr; m:(str:'IRET');
  474.                       Next:@WSeoln; Alt:@TryBrk; Success:SetIret);
  475.  
  476.      TryHalt:TPattern=( mf:MatchiStr; m:(str:'HALT');
  477.                       Next:@WSeoln; Alt:@TryIRet; Success:SetHalt);
  478.  
  479.      TryPut:TPattern=( mf:MatchiStr; m:(str:'PUT');
  480.                       Next:@WSeoln; Alt:@TryHalt; Success:SetPut);
  481.  
  482.      TryGet:TPattern=( mf:MatchiStr; m:(str:'GET');
  483.                       Next:@WSeoln; Alt:@TryPut; Success:SetGet);
  484.  
  485.      { Jump Instructions here: }
  486.  
  487.      JmpLbl2:TPattern=(mf:GetLbl; m:(ch:' ');
  488.                         Next:NIL; Alt:NIL; Success:NIL);
  489.  
  490.      JmpLbl:TPattern=(mf:OneOrMoreCset; m:(cset:[' ',#9]);
  491.                         Next:@JmpLbl2; Alt:NIL; Success:NIL);
  492.  
  493.      TryJne:TPattern=(mf:MatchiStr; m:(str:'JNE');
  494.                         Next:@JmpLbl; Alt:@TryGet; Success:SetJne);
  495.  
  496.      TryJe:TPattern=(mf:MatchiStr; m:(str:'JE');
  497.                         Next:@JmpLbl; Alt:@TryJne; Success:SetJe);
  498.  
  499.      TryJb:TPattern=(mf:MatchiStr; m:(str:'JB');
  500.                         Next:@JmpLbl; Alt:@TryJe; Success:SetJb);
  501.  
  502.      TryJbe:TPattern=(mf:MatchiStr; m:(str:'JBE');
  503.                         Next:@JmpLbl; Alt:@TryJb; Success:SetJbe);
  504.  
  505.      TryJa:TPattern=(mf:MatchiStr; m:(str:'JA');
  506.                         Next:@JmpLbl; Alt:@TryJbe; Success:SetJa);
  507.  
  508.      TryJae:TPattern=(mf:MatchiStr; m:(str:'JAE');
  509.                         Next:@JmpLbl; Alt:@TryJa; Success:SetJae);
  510.  
  511.      TryJmp:TPattern=(mf:MatchiStr; m:(str:'JMP');
  512.                         Next:@JmpLbl; Alt:@TryJae; Success:SetJmp);
  513.  
  514.  
  515.  
  516.      { not reg/mem here: }
  517.  
  518.      GenMemMode:TPattern=( mf:MatchSub; m:(Pat:@DoMem);
  519.                           Next:@WSeoln; Alt:NIL; Success:NIL);
  520.  
  521.  
  522.      NotWS:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  523.                      Next:@GenMemMode; Alt:NIL; Success:NIL);
  524.  
  525.      TryNotInstr:TPattern=( mf:MatchiStr; m:(str:'NOT');
  526.                            Next:@NotWS; Alt:@TryJmp; Success:SetNot);
  527.  
  528.  
  529.  
  530.      { instr reg, mem here: }
  531.  
  532.      WSComma2:TPattern=( mf:SpanCset; m:(cset:[' ',',',#9]);
  533.                          Next:@GenMemMode; Alt:NIL; Success:NIL);
  534.  
  535.      GenRegMem:TPattern=(mf:MatchSub; m:(Pat:@TryReg);
  536.                      Next:@WSComma2; Alt:NIL; Success:NIL);
  537.  
  538.      InstrWS:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  539.                      Next:@GenRegMem; Alt:NIL; Success:NIL);
  540.  
  541.      TryGeneric:TPattern=( mf:MatchSub; m:(Pat:@TryAdd);
  542.                            Next:@InstrWS; Alt:@TryNotInstr; Success:NIL);
  543.  
  544.  
  545.  
  546.      { mov mem, reg here: }
  547.  
  548.      MovReg:TPattern=(mf:MatchSub; m:(Pat:@TryReg);
  549.                      Next:@WSeoln; Alt:NIL; Success:SetMovMem);
  550.  
  551.      WSComma3:TPattern=( mf:SpanCset; m:(cset:[' ',',',#9]);
  552.                        Next:@MovReg; Alt:NIL; Success:NIL);
  553.  
  554.      MemReg:TPattern=( mf:MatchSub; m:(Pat:@DoMem);
  555.                        Next:@WSComma3; Alt:NIL; Success:NIL);
  556.  
  557.  
  558.      { mov reg, mem here: }
  559.  
  560.      MemMode:TPattern=( mf:MatchSub; m:(Pat:@DoMem);
  561.                        Next:@WSeoln; Alt:NIL; Success:SetMovReg);
  562.  
  563.      WSComma:TPattern=( mf:SpanCset; m:(cset:[' ',',',#9]);
  564.                        Next:@MemMode; Alt:NIL; Success:NIL);
  565.  
  566.      RgMem:TPattern=(mf:MatchSub; m:(Pat:@TryReg);
  567.                      Next:@WSComma; Alt:@MemReg; Success:NIL);
  568.  
  569.      { Generic mov here: }
  570.  
  571.      MovWS:TPattern=(mf:SpanCset; m:(cset:[' ',#9]);
  572.                      Next:@RgMem; Alt:NIL; Success:NIL);
  573.  
  574.      TryMnemonic:TPattern=(mf:MatchiStr; m:(str:'MOV');
  575.                       Next:@MovWS; Alt:@TryGeneric; Success:NIL);
  576.  
  577.  
  578.  
  579.  
  580.      TryEOS:TPattern=(mf:EOS; m:(ch:' ');
  581.                       Next:NIL; Alt:@TryMnemonic; Success:NIL);
  582.  
  583.      TryWS:TPattern =(mf:SpanCset; m:(cset:[' ',#9]);
  584.                       Next:@TryEOS; Alt:NIL; Success:NIL);
  585.  
  586.      stmt:TPattern = (mf:MatchSub; m:(Pat:@Lbl);
  587.                       Next:@TryMnemonic; Alt:@TryWS; Success:NIL);
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596. { System initialization }
  597.  
  598.  
  599. procedure TSIMx86Form.FormCreate(Sender: TObject);
  600. var     i:    word;
  601.     ch:    char;
  602. begin
  603.  
  604.  
  605.     { Allocate Storage for the x86 memory space }
  606.  
  607.     system.new(Memory);
  608.  
  609.     { Zero out the allocated memory }
  610.  
  611.     for i := 0 to $ffef do
  612.         Memory^[i] := 0;
  613.  
  614.     MemAdrs := 0;
  615.     MemWS := 0;
  616.     IntAdrs := $FFFF;
  617.     Adrs := 0;
  618.     AX := 0;
  619.     BX := 0;
  620.     CX := 0;
  621.     DX := 0;
  622.     IP := 0;
  623.  
  624.     MemEntry[0,0] := Mem00;
  625.     MemEntry[0,1] := Mem01;
  626.     MemEntry[0,2] := Mem02;
  627.     MemEntry[0,3] := Mem03;
  628.     MemEntry[0,4] := Mem04;
  629.     MemEntry[0,5] := Mem05;
  630.     MemEntry[0,6] := Mem06;
  631.     MemEntry[0,7] := Mem07;
  632.  
  633.     MemEntry[1,0] := Mem10;
  634.     MemEntry[1,1] := Mem11;
  635.     MemEntry[1,2] := Mem12;
  636.     MemEntry[1,3] := Mem13;
  637.     MemEntry[1,4] := Mem14;
  638.     MemEntry[1,5] := Mem15;
  639.     MemEntry[1,6] := Mem16;
  640.     MemEntry[1,7] := Mem17;
  641.  
  642.     MemEntry[2,0] := Mem20;
  643.     MemEntry[2,1] := Mem21;
  644.     MemEntry[2,2] := Mem22;
  645.     MemEntry[2,3] := Mem23;
  646.     MemEntry[2,4] := Mem24;
  647.     MemEntry[2,5] := Mem25;
  648.     MemEntry[2,6] := Mem26;
  649.     MemEntry[2,7] := Mem27;
  650.  
  651.     MemEntry[3,0] := Mem30;
  652.     MemEntry[3,1] := Mem31;
  653.     MemEntry[3,2] := Mem32;
  654.     MemEntry[3,3] := Mem33;
  655.     MemEntry[3,4] := Mem34;
  656.     MemEntry[3,5] := Mem35;
  657.     MemEntry[3,6] := Mem36;
  658.     MemEntry[3,7] := Mem37;
  659.  
  660.     MemEntry[4,0] := Mem40;
  661.     MemEntry[4,1] := Mem41;
  662.     MemEntry[4,2] := Mem42;
  663.     MemEntry[4,3] := Mem43;
  664.     MemEntry[4,4] := Mem44;
  665.     MemEntry[4,5] := Mem45;
  666.     MemEntry[4,6] := Mem46;
  667.     MemEntry[4,7] := Mem47;
  668.  
  669.     MemEntry[5,0] := Mem50;
  670.     MemEntry[5,1] := Mem51;
  671.     MemEntry[5,2] := Mem52;
  672.     MemEntry[5,3] := Mem53;
  673.     MemEntry[5,4] := Mem54;
  674.     MemEntry[5,5] := Mem55;
  675.     MemEntry[5,6] := Mem56;
  676.     MemEntry[5,7] := Mem57;
  677.  
  678.     MemEntry[6,0] := Mem60;
  679.     MemEntry[6,1] := Mem61;
  680.     MemEntry[6,2] := Mem62;
  681.     MemEntry[6,3] := Mem63;
  682.     MemEntry[6,4] := Mem64;
  683.     MemEntry[6,5] := Mem65;
  684.     MemEntry[6,6] := Mem66;
  685.     MemEntry[6,7] := Mem67;
  686.  
  687.     MemEntry[7,0] := Mem70;
  688.     MemEntry[7,1] := Mem71;
  689.     MemEntry[7,2] := Mem72;
  690.     MemEntry[7,3] := Mem73;
  691.     MemEntry[7,4] := Mem74;
  692.     MemEntry[7,5] := Mem75;
  693.     MemEntry[7,6] := Mem76;
  694.     MemEntry[7,7] := Mem77;
  695.  
  696.     { See if there were any command-line parameters }
  697.  
  698.     if (ParamCount = 1) then
  699.     begin
  700.  
  701.         SourceCode.Lines.LoadFromFile(ParamStr(1));
  702.         Filename := ParamStr(1);
  703.  
  704.     end
  705.     else Filename := '';
  706.  
  707.  
  708. end;
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715. (****************************************************************************)
  716.  
  717.  
  718. {$R *.DFM}
  719.  
  720.  
  721. { Read a byte from memory.  Also handles memory-mapped I/O (locations    }
  722. { $FFF0.$FFFF are memory-mapped I/O locations).                }
  723. {                                    }
  724. { $FFF0 (bit 0)-    Switch zero.                    }
  725. { $FFF2 (bit 0)-    Switch one.                    }
  726. { $FFF4 (bit 0)-    Switch two.                    }
  727. { $FFF6 (bit 0)-    Switch three.                    }
  728. {     All other bit positions return zero in the above words.        }
  729. {                                    }
  730. {    Locations $FFF8..$FFFF are write-only locations and return    }
  731. {    random garbage.                            }
  732.  
  733. function ReadMem(adrs:word):byte;
  734. begin
  735.  
  736.     if (adrs < $fff0) then Result := Memory^[adrs]
  737.         else begin
  738.  
  739.             with SIMx86Form do begin
  740.  
  741.             if (Adrs = $fff0) then Result := ord(Inport0.pOn)
  742.                 else if (Adrs = $fff2) then Result := ord(Inport2.pOn)
  743.                 else if (Adrs = $fff4) then Result := ord(Inport4.pOn)
  744.                 else if (Adrs = $fff6) then Result := ord(Inport6.pOn)
  745.                 else if (Adrs = $fff1) or (Adrs=$FFF3) or
  746.                     (Adrs = $fff5) or (Adrs=$fff7) then Result := 0;
  747.  
  748.             end;
  749.  
  750.         end;
  751.  
  752. end;
  753.  
  754.  
  755.  
  756. { WriteMem-    Write a byte to memory.  Note that locations    }
  757. {        $FFF0..$FFFF are memory mapped I/O locations    }
  758. {        and must be handled specially.  Only the low-    }
  759. {        order bit of locations $FFF8, $FFFA, $FFFC, and    }
  760. {        $FFFE are active outputs;  these bits cor-    }
  761. {        respond to the four LEDs.  The other memory-    }
  762. {        mapped I/O locations ignore data written to them}
  763.  
  764. procedure WriteMem(Adrs:word; Value:word);
  765. begin
  766.  
  767.     if (Adrs < $fff0) then
  768.             Memory^[Adrs] := Value
  769.         else begin
  770.  
  771.             with SIMx86Form do begin
  772.  
  773.             if (Adrs = $fff8) then
  774.                     if (odd(Value)) then Outport8.Brush.Color := clRed
  775.                         else Outport8.Brush.Color := clWhite
  776.                 else if (Adrs = $fffa) then
  777.                     if (odd(Value)) then OutportA.Brush.Color := clRed
  778.                         else OutportA.Brush.Color := clWhite
  779.                 else if (Adrs = $fffC) then
  780.                     if (odd(Value)) then OutportC.Brush.Color := clRed
  781.                         else OutportC.Brush.Color := clWhite
  782.                 else if (Adrs = $fffe) then
  783.                     if (odd(Value)) then OutportE.Brush.Color := clRed
  784.                         else OutportE.Brush.Color := clWhite;
  785.  
  786.             end;
  787.         end;
  788.  
  789. end;
  790.  
  791.  
  792.  
  793. { Print an error message dialog box for the assembler. }
  794.  
  795. procedure ErrorMsg(const msg, Stmt:string);
  796. begin
  797.  
  798.      AbortAsm := MessageDlg(msg+': '+Stmt,
  799.                             mtWarning,[mbOK, mbCancel],0) = mrCancel;
  800.      NoError := false;
  801.  
  802. end;
  803.  
  804.  
  805. { The following function converts a string of characters representing a    }
  806. { hexadecimal number into the binary equivalent.            }
  807.  
  808. function HexToWord(const s:string):word;
  809. var i:integer;
  810. begin
  811.  
  812.      Result := 0;
  813.      for i := 1 to length(s) do
  814.          if (s[i] in ['0'..'9']) then
  815.             Result := (Result shl 4) + ord(s[i]) - ord('0')
  816.          else
  817.             Result := (Result shl 4) + ord(upcase(s[i])) -
  818.                               ord('A') + 10;
  819. end;
  820.  
  821.  
  822.  
  823.  
  824. { CheckHex-    This procedure checks a TEdit object to see if its text    }
  825. {        field contains a valid hexadecimal value.  It turns the    }
  826. {        background red if invalid.                }
  827.  
  828. procedure CheckHex(var s:TEdit);
  829. var i:integer;
  830. begin
  831.  
  832.     s.Color := clWindow;
  833.     for i := 1 to length(s.Text) do
  834.         if not (s.Text[i] in ['0'..'9','A'..'F','a'..'f']) then
  835.         begin
  836.  
  837.            s.Color := clRed;
  838.            MessageBeep($FFFF);
  839.  
  840.         end;
  841.  
  842. end;
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849. {$F+}
  850.  
  851. { Whenever the assembler encounters a label at the beginning of a line,    }
  852. { the following function checks to see if it is a legal label and adds    }
  853. { it to the symbol table along with its address.  It also backpatches    }
  854. { any previous references to that symbol if there are any.        }
  855.  
  856. function ProcessLbl(Pat:TPatPtr):boolean;
  857. var id:    char;
  858.     i,
  859.     tmp:word;
  860. begin
  861.  
  862.      id :=upcase(Pat^.EndPattern^);
  863.  
  864.      { See if this is a legal label }
  865.  
  866.      if (id in ['A'..'Z']) and ((Pat^.EndPattern+1)^ = ':') then
  867.      begin
  868.  
  869.            {See if this symbol is already in the symbol table.    }
  870.  
  871.           if SymTbl[id].Defined then
  872.           begin
  873.  
  874.              ErrorMsg('Duplicate Identifier',
  875.                    SIMx86Form.SourceCode.lines[LineNum]);
  876.  
  877.           end
  878.           else begin
  879.  
  880.                { See if this symbol was used already.    }
  881.                { If so, we need to backpatch some    }
  882.                { addresses in memory.            }
  883.  
  884.                if (SymTbl[id].Value <> 0) then
  885.                begin
  886.  
  887.                   i := SymTbl[id].Value;
  888.                   repeat
  889.  
  890.                        tmp := Memory^[i] + (Memory^[i+1] shl 8);
  891.                        Memory^[i] := Adrs and $ff;
  892.                         Memory^[i+1] := Adrs shr 8;
  893.                         i := tmp;
  894.  
  895.                    until i = 0;
  896.  
  897.                end;
  898.  
  899.                { Put all the necessary information into the symbol table. }
  900.  
  901.                SymTbl[id].Defined := true;
  902.                SymTbl[id].Value := adrs;
  903.                Result := true;
  904.  
  905.                { Skip over any white space following this label. }
  906.  
  907.                Pat^.EndPattern := Pat^.EndPattern + 2;
  908.                While (Pat^.EndPattern^ in [' ',#9]) do
  909.                      inc(Pat^.EndPattern);
  910.  
  911.           end;
  912.  
  913.  
  914.      end
  915.      else Result := false;
  916.  
  917. end;
  918.  
  919.  
  920. { ConvertHex-    Converts the text field of a PChar object into a binary    }
  921. {        value and return true if the result is successful.    }
  922. {        This routine shoves the binary result into the global    }
  923. {        variable OperandValue.  The assembler uses this func    }
  924. {        to process hexadecimal instruction operands.        }
  925.  
  926. function ConvertHex(Pat:TPatPtr):Boolean;
  927. var i:integer;
  928. begin
  929.  
  930.      OperandValue := 0;
  931.      Result := Pat^.EndPattern^ in ['0'..'9', 'a'..'f', 'A'..'F'];
  932.      HasValue := true;
  933.      while (Pat^.EndPattern^ in ['0'..'9', 'a'..'f', 'A'..'F']) do
  934.      begin
  935.  
  936.          if (Pat^.EndPattern^  in ['0'..'9']) then
  937.             OperandValue := (OperandValue shl 4) +
  938.                          ord(Pat^.EndPattern^) - ord('0')
  939.          else
  940.             OperandValue := ( OperandValue shl 4) +
  941.                           ord(upcase(Pat^.EndPattern^ )) -
  942.                               ord('A') + 10;
  943.  
  944.          inc(Pat^.EndPattern);
  945.  
  946.      end;
  947. end;
  948.  
  949.  
  950.  
  951. { GetLbl-    The assembler uses this function to process labels it    }
  952. {        finds in the operand field of a jump instruction.    }
  953.  
  954. function GetLbl(Pat:TPatPtr):boolean;
  955. var id:char;
  956. begin
  957.  
  958.      id :=upcase(Pat^.EndPattern^);
  959.      Result := false;
  960.  
  961.      { If the operand begins with a decimal digit, it's a hexadecimal    }
  962.      { number, not a label.                        }
  963.  
  964.      if (id in ['0'..'9']) then
  965.      begin
  966.  
  967.         HasValue := ConvertHex(Pat);
  968.         while (Pat^.EndPattern^ in [' ',#9]) do inc(Pat^.EndPattern);
  969.         Result := Pat^.EndPattern^ = #0;
  970.  
  971.      end
  972.  
  973.      { If the operand begins with an alphabetic character, then we've    }
  974.      { got a label.                            }
  975.  
  976.      else if (id in ['A'..'Z']) then
  977.      begin
  978.  
  979.            HasValue := true;
  980.            if (not SymTbl[id].Defined) then
  981.           begin
  982.  
  983.               { If the symbol is not defined yet, create a linked }
  984.                 { list of undefined items for this symbol.        }
  985.  
  986.               OperandValue := SymTbl[id].Value;
  987.                 SymTbl[id].Value := adrs+1;
  988.  
  989.           end
  990.           else OperandValue := SymTbl[id].Value;
  991.  
  992.           repeat
  993.  
  994.                 inc(Pat^.EndPattern);
  995.  
  996.           until not (Pat^.EndPattern^ in [' ',#9]);
  997.           Result := Pat^.EndPattern^ = #0;
  998.  
  999.      end
  1000.      else begin
  1001.  
  1002.           ErrorMsg('Expected label operand',
  1003.                    SIMx86Form.SourceCode.lines[LineNum]);
  1004.  
  1005.      end;
  1006.  
  1007.  
  1008. end;
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016. { The assembler calls the following procedure whenever it encounters    }
  1017. { the corresponding procedure or operand.  These procedures set up the    }
  1018. { global opcode and operand values so the assembler can emit the ap-    }
  1019. { propriate object code later.                        }
  1020.  
  1021. Procedure SetJmp(Pat:TPatPtr);
  1022. begin
  1023.  
  1024.      HasOpcode := True;
  1025.      Opcode := $0;
  1026.      HasReg := true;
  1027.      RegCode := $8;
  1028.      HasOperand := true;
  1029.      OperandCode := $6;
  1030.  
  1031. end;
  1032.  
  1033. Procedure SetJa(Pat:TPatPtr);
  1034. begin
  1035.  
  1036.      HasOpcode := True;
  1037.      Opcode := $0;
  1038.      HasReg := true;
  1039.      RegCode := $8;
  1040.      HasOperand := true;
  1041.      OperandCode := $4;
  1042.  
  1043. end;
  1044.  
  1045. Procedure SetJae(Pat:TPatPtr);
  1046. begin
  1047.  
  1048.      HasOpcode := True;
  1049.      Opcode := $0;
  1050.      HasReg := true;
  1051.      RegCode := $8;
  1052.      HasOperand := true;
  1053.      OperandCode := $5;
  1054.  
  1055. end;
  1056.  
  1057. Procedure SetJb(Pat:TPatPtr);
  1058. begin
  1059.  
  1060.      HasOpcode := True;
  1061.      Opcode := $0;
  1062.      HasReg := true;
  1063.      RegCode := $8;
  1064.      HasOperand := true;
  1065.      OperandCode := $2;
  1066.  
  1067. end;
  1068.  
  1069. Procedure SetJbe(Pat:TPatPtr);
  1070. begin
  1071.  
  1072.      HasOpcode := True;
  1073.      Opcode := $0;
  1074.      HasReg := true;
  1075.      RegCode := $8;
  1076.      HasOperand := true;
  1077.      OperandCode := $3;
  1078.  
  1079. end;
  1080.  
  1081. Procedure SetJe(Pat:TPatPtr);
  1082. begin
  1083.  
  1084.      HasOpcode := True;
  1085.      Opcode := $0;
  1086.      HasReg := true;
  1087.      RegCode := $8;
  1088.      HasOperand := true;
  1089.      OperandCode := $0;
  1090.  
  1091. end;
  1092.  
  1093. Procedure SetJne(Pat:TPatPtr);
  1094. begin
  1095.  
  1096.      HasOpcode := True;
  1097.      Opcode := $0;
  1098.      HasReg := true;
  1099.      RegCode := $8;
  1100.      HasOperand := true;
  1101.      OperandCode := $1;
  1102.  
  1103. end;
  1104.  
  1105.  
  1106. Procedure SetNot(Pat:TPatPtr);
  1107. begin
  1108.  
  1109.      HasOpcode := True;
  1110.      Opcode := $0;
  1111.      HasReg := true;
  1112.      RegCode := $10;
  1113.  
  1114. end;
  1115.  
  1116. Procedure SetOr(Pat:TPatPtr);
  1117. begin
  1118.  
  1119.      HasOpcode := True;
  1120.      Opcode := $20;
  1121.  
  1122. end;
  1123.  
  1124. Procedure SetAnd(Pat:TPatPtr);
  1125. begin
  1126.  
  1127.      HasOpcode := True;
  1128.      Opcode := $40;
  1129.  
  1130. end;
  1131.  
  1132. Procedure SetCmp(Pat:TPatPtr);
  1133. begin
  1134.  
  1135.      HasOpcode := True;
  1136.      Opcode := $60;
  1137.  
  1138. end;
  1139.  
  1140. Procedure SetSub(Pat:TPatPtr);
  1141. begin
  1142.  
  1143.      HasOpcode := True;
  1144.      Opcode := $80;
  1145.  
  1146. end;
  1147.  
  1148. Procedure SetAdd(Pat:TPatPtr);
  1149. begin
  1150.  
  1151.      HasOpcode := True;
  1152.      Opcode := $A0;
  1153.  
  1154. end;
  1155.  
  1156. Procedure SetMovReg(Pat:TPatPtr);
  1157. begin
  1158.  
  1159.      HasOpcode := True;
  1160.      Opcode := $C0;
  1161.  
  1162. end;
  1163.  
  1164. Procedure SetMovMem(Pat:TPatPtr);
  1165. begin
  1166.  
  1167.      HasOpcode := True;
  1168.      Opcode := $E0;
  1169.  
  1170. end;
  1171.  
  1172. Procedure SetBRK(Pat:TPatPtr);
  1173. begin
  1174.  
  1175.      HasOpcode := True;
  1176.      Opcode := $0;
  1177.      HasReg := true;
  1178.      RegCode := $0;
  1179.      HasOperand := true;
  1180.      OperandCode := $3;
  1181.  
  1182. end;
  1183.  
  1184. Procedure SetIret(Pat:TPatPtr);
  1185. begin
  1186.  
  1187.      HasOpcode := True;
  1188.      Opcode := $0;
  1189.      HasReg := true;
  1190.      RegCode := $0;
  1191.      HasOperand := true;
  1192.      OperandCode := $4;
  1193.  
  1194. end;
  1195.  
  1196. Procedure SetHalt(Pat:TPatPtr);
  1197. begin
  1198.  
  1199.      HasOpcode := True;
  1200.      Opcode := $0;
  1201.      HasReg := true;
  1202.      RegCode := $0;
  1203.      HasOperand := true;
  1204.      OperandCode := $5;
  1205.  
  1206. end;
  1207.  
  1208. Procedure SetPut(Pat:TPatPtr);
  1209. begin
  1210.  
  1211.      HasOpcode := True;
  1212.      Opcode := $0;
  1213.      HasReg := true;
  1214.      RegCode := $0;
  1215.      HasOperand := true;
  1216.      OperandCode := $7;
  1217.  
  1218. end;
  1219.  
  1220. Procedure SetGet(Pat:TPatPtr);
  1221. begin
  1222.  
  1223.      HasOpcode := True;
  1224.      Opcode := $0;
  1225.      HasReg := true;
  1226.      RegCode := $0;
  1227.      HasOperand := true;
  1228.      OperandCode := $6;
  1229.  
  1230. end;
  1231.  
  1232.  
  1233.  
  1234.  
  1235. Procedure SetAX(Pat:TPatPtr);
  1236. begin
  1237.  
  1238.      HasReg := True;
  1239.      Regcode := $00;
  1240.  
  1241. end;
  1242.  
  1243. Procedure SetBX(Pat:TPatPtr);
  1244. begin
  1245.  
  1246.      HasReg := True;
  1247.      Regcode := $08;
  1248.  
  1249. end;
  1250.  
  1251. Procedure SetCX(Pat:TPatPtr);
  1252. begin
  1253.  
  1254.      HasReg := True;
  1255.      Regcode := $10;
  1256.  
  1257. end;
  1258.  
  1259. Procedure SetDX(Pat:TPatPtr);
  1260. begin
  1261.  
  1262.      HasReg := True;
  1263.      Regcode := $18;
  1264.  
  1265. end;
  1266.  
  1267.  
  1268.  
  1269.  
  1270. Procedure SetAX2(Pat:TPatPtr);
  1271. begin
  1272.  
  1273.      HasOperand := True;
  1274.      Operandcode := $00;
  1275.  
  1276. end;
  1277.  
  1278. Procedure SetBX2(Pat:TPatPtr);
  1279. begin
  1280.  
  1281.      HasOperand := True;
  1282.      Operandcode := $1;
  1283.  
  1284. end;
  1285.  
  1286. Procedure SetCX2(Pat:TPatPtr);
  1287. begin
  1288.  
  1289.      HasOperand := True;
  1290.      Operandcode := $2;
  1291.  
  1292. end;
  1293.  
  1294. Procedure SetDX2(Pat:TPatPtr);
  1295. begin
  1296.  
  1297.      HasOperand := True;
  1298.      Operandcode := $3;
  1299.  
  1300. end;
  1301.  
  1302. Procedure SetBXInd(Pat:TPatPtr);
  1303. begin
  1304.  
  1305.      HasOperand := True;
  1306.      Operandcode := $4;
  1307.  
  1308. end;
  1309.  
  1310. Procedure SetBXIndx(Pat:TPatPtr);
  1311. begin
  1312.  
  1313.      HasOperand := True;
  1314.      Operandcode := $5;
  1315.  
  1316. end;
  1317.  
  1318. Procedure SetABS(Pat:TPatPtr);
  1319. begin
  1320.  
  1321.      HasOperand := True;
  1322.      Operandcode := $6;
  1323.  
  1324. end;
  1325.  
  1326. Procedure SetImm(Pat:TPatPtr);
  1327. begin
  1328.  
  1329.      HasOperand := True;
  1330.      Operandcode := $7;
  1331.  
  1332. end;
  1333.  
  1334. {$F-}
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348. { Whenever the user presses the CLEAR button on the memory page, the    }
  1349. { following method zeros out memory.                    }
  1350.  
  1351. procedure TSIMx86Form.ClrMemBtnClick(Sender: TObject);
  1352. var i:word;
  1353. begin
  1354.  
  1355.     AdrsEntry.Text := '0000';
  1356.     AdrsEntryChange(AdrsEntry);
  1357.  
  1358.     { Zero out memory }
  1359.  
  1360.     for i := 0 to $ffef do
  1361.         Memory^[i] := 0;
  1362.  
  1363.     MemAdrs := 0;
  1364.     Adrs := 0;
  1365.  
  1366. end;
  1367.  
  1368.  
  1369.  
  1370.  
  1371. { Handle the NEW, OPEN, SAVE, SAVEAS, Print, and QUIT entries in the File Menu }
  1372.  
  1373. procedure TSIMx86Form.QuitClick(Sender: TObject);
  1374. begin
  1375.  
  1376.     Application.Terminate;
  1377.  
  1378. end;
  1379.  
  1380.  
  1381.  
  1382. procedure TSIMx86Form.PrintMenuItemClick(Sender: TObject);
  1383. var
  1384.     i: integer;
  1385.     f: TextFile;
  1386.  
  1387. begin
  1388.  
  1389.     if PrintDialog.Execute then begin
  1390.  
  1391.       if (SIMx86Pages.PageIndex = 0) then begin
  1392.  
  1393.         AssignPrn(f);
  1394.         Rewrite(f);
  1395.  
  1396.     for i := 0 to SourceCode.Lines.Count-1 do
  1397.             writeln(f,SourceCode.Lines[i]);
  1398.  
  1399.         CloseFile(f);
  1400.  
  1401.       end
  1402.       else Print;
  1403.  
  1404.     end;
  1405.  
  1406. end;
  1407.  
  1408.  
  1409.  
  1410. procedure TSIMx86Form.NewClick(Sender: TObject);
  1411. begin
  1412.  
  1413.     SourceCode.Clear;
  1414.     Filename := '';
  1415.  
  1416. end;
  1417.  
  1418. procedure TSIMx86Form.OpenClick(Sender: TObject);
  1419. var
  1420.     name:string;
  1421.  
  1422. begin
  1423.  
  1424.     if OpenDialog.Execute then
  1425.     begin
  1426.  
  1427.         SourceCode.Lines.LoadFromFile(OpenDialog.Filename);
  1428.         Filename := OpenDialog.Filename;
  1429.  
  1430.     end;
  1431.  
  1432. end;
  1433.  
  1434. procedure TSIMx86Form.SaveAsClick(Sender: TObject);
  1435. begin
  1436.  
  1437.     if SaveDialog.Execute then
  1438.     begin
  1439.  
  1440.         FileName := SaveDialog.Filename;
  1441.         SourceCode.Lines.SaveToFile(SaveDialog.Filename);
  1442.  
  1443.     end;
  1444.  
  1445. end;
  1446.  
  1447. procedure TSIMx86Form.SaveClick(Sender: TObject);
  1448. begin
  1449.  
  1450.     if (Filename = '') then
  1451.     begin
  1452.         if SaveDialog.Execute then
  1453.            Filename := SaveDialog.Filename;
  1454.  
  1455.     end;
  1456.  
  1457.     if (Filename <> '') then
  1458.     begin
  1459.  
  1460.         SourceCode.Lines.SaveToFile(Filename);
  1461.  
  1462.     end;
  1463.  
  1464.  
  1465.  
  1466. end;
  1467.  
  1468.  
  1469.  
  1470.  
  1471. { Handle Cut, Copy, Paste, Delete, and SelectAll in the Edit Menu }
  1472.  
  1473. procedure TSIMx86Form.CutClick(Sender: TObject);
  1474. begin
  1475.  
  1476.     SourceCode.CutToClipBoard;
  1477.  
  1478. end;
  1479.  
  1480. procedure TSIMx86Form.CopyClick(Sender: TObject);
  1481. begin
  1482.  
  1483.     SourceCode.CopyToClipBoard;
  1484.  
  1485. end;
  1486.  
  1487. procedure TSIMx86Form.PasteClick(Sender: TObject);
  1488. begin
  1489.  
  1490.     SourceCode.PasteFromClipBoard;
  1491.  
  1492. end;
  1493.  
  1494. procedure TSIMx86Form.DeleteClick(Sender: TObject);
  1495. begin
  1496.  
  1497.     SourceCode.ClearSelection;
  1498.  
  1499. end;
  1500.  
  1501. procedure TSIMx86Form.SelectAllClick(Sender: TObject);
  1502. begin
  1503.  
  1504.     SourceCode.SelectAll;
  1505.     SourceCode.Repaint;
  1506.  
  1507. end;
  1508.  
  1509.  
  1510.  
  1511.  
  1512. { Whenver a value changes in one of the memory data entry boxes, this    }
  1513. { method converts the data data to hexadecimal and stores the resulting    }
  1514. { value away into memory.                        }
  1515.  
  1516. procedure TSIMx86Form.HexChange(Sender: TObject);
  1517. var Cell:TEdit;
  1518.     HexVal:byte;
  1519.     i,
  1520.     j,
  1521.     index:word;
  1522.  
  1523. begin
  1524.  
  1525.     Cell := TEdit(Sender);
  1526.     CheckHex(Cell);
  1527.  
  1528.     { Only store the data if there is no error.  If there is an error,    }
  1529.     { the memory cell's background color will be red.            }
  1530.  
  1531.     if (Cell.Color <> clRed) then
  1532.     begin
  1533.  
  1534.         for i := 0 to 7 do
  1535.             for j := 0 to 7 do
  1536.                 if (Sender = MemEntry[i,j]) then
  1537.                     WriteMem(MemAdrs+ i*8+j, HexToWord(Cell.Text));
  1538.  
  1539.     end;
  1540.  
  1541. end;
  1542.  
  1543.  
  1544.  
  1545.  
  1546. { AdrsEntryChange-    This method executes whenever the user changes    }
  1547. {            a value in the address box on the Memory page.    }
  1548. {            This method converts the string representation    }
  1549. {            of the address to binary, updates all the labels}
  1550. {            on the screen, and then updates all the memory    }
  1551. {            entry boxes on the page.            }
  1552.  
  1553. procedure TSIMx86Form.AdrsEntryChange(Sender: TObject);
  1554. var
  1555.     HexVal:    word;
  1556.     index:    word;
  1557.     i,j:    word;
  1558.  
  1559. begin
  1560.  
  1561.     CheckHex(TEdit(Sender));
  1562.  
  1563.     { If the entry is invalid, don't do anything.    }
  1564.  
  1565.     if (AdrsEntry.Color <> clRed) then begin
  1566.  
  1567.         HexVal := HexToWord(AdrsEntry.Text);
  1568.  
  1569.         { Update the labels on the page.  Make sure the values we use    }
  1570.         { are all even multiples of eight.                }
  1571.  
  1572.         MemAdrs := HexVal and $FFF8;
  1573.         Lbl8.Caption  := IntToHex(MemAdrs+8,4);
  1574.         Lbl10.Caption := IntToHex(MemAdrs+16,4);
  1575.         Lbl18.Caption := IntToHex(MemAdrs+24,4);
  1576.         Lbl20.Caption := IntToHex(MemAdrs+32,4);
  1577.         Lbl28.Caption := IntToHex(MemAdrs+40,4);
  1578.         Lbl30.Caption := IntToHex(MemAdrs+48,4);
  1579.         Lbl38.Caption := IntToHex(MemAdrs+56,4);
  1580.  
  1581.         { Update the data in the entry cells on the page.  If    }
  1582.         { the location we access is before the starting address    }
  1583.         { (because we may have rounded it down to the previous    }
  1584.         {  eight-byte boundary), then turn the background color    }
  1585.         { gray.                            }
  1586.  
  1587.         for i := 0 to 7 do
  1588.             for j := 0 to 7 do
  1589.             begin
  1590.  
  1591.                 index := MemAdrs + i*8 + j;
  1592.                 MemEntry[i,j].Text := IntToHex(ReadMem(index),2);
  1593.                 if ((index < HexVal) or (Index >=$fff0)) then
  1594.                 begin
  1595.  
  1596.                     MemEntry[i,j].Color := clSilver;
  1597.                         MemEntry[i,j].Enabled := false;
  1598.  
  1599.                 end
  1600.                 else begin
  1601.  
  1602.                     MemEntry[i,j].Color := clWindow;
  1603.                         MemEntry[i,j].Enabled := true;
  1604.  
  1605.                 end;
  1606.  
  1607.             end;
  1608.  
  1609.  
  1610.     end;
  1611.  
  1612. end;
  1613.  
  1614.  
  1615.  
  1616. procedure TSIMx86Form.StartAdrsChange(Sender: TObject);
  1617. begin
  1618.  
  1619.     CheckHex(StartAdrs);
  1620.  
  1621. end;
  1622.  
  1623.  
  1624.  
  1625. { Do the assembly here }
  1626.  
  1627. procedure TSIMx86Form.ASMbtnClick(Sender: TObject);
  1628. var
  1629.    i:word;
  1630.    ch:char;
  1631.    line:array[0..255] of char;
  1632.    s:PChar;
  1633.  
  1634. begin
  1635.  
  1636.      { Initialize the symbol table }
  1637.  
  1638.      for ch := 'A' to 'Z' do
  1639.      begin
  1640.  
  1641.           SymTbl[ch].Value := 0;
  1642.           SymTbl[ch].Defined := false;
  1643.  
  1644.      end;
  1645.  
  1646.      { Compute the address of the first instruction }
  1647.  
  1648.      if (StartAdrs.Color <> clRed) then
  1649.          Adrs := HexToWord(StartAdrs.Text)
  1650.      else Adrs := 0;
  1651.  
  1652.      { Assemble each line of source code }
  1653.  
  1654.      for LineNum := 0 to SourceCode.Lines.Count-1 do begin
  1655.  
  1656.          s := strPCopy(line, SourceCode.Lines[LineNum]);
  1657.          NoError := true;
  1658.          HasValue := false;
  1659.          HasOpcode := false;
  1660.          HasReg := false;
  1661.          HasOperand := false;
  1662.          if (not Match(stmt, s)) then
  1663.          begin
  1664.  
  1665.            if (NoError) then
  1666.               ErrorMsg('Syntax Error',
  1667.                    SourceCode.lines[LineNum]);
  1668.            if (AbortAsm) then break;
  1669.  
  1670.          end
  1671.          else begin
  1672.  
  1673.  
  1674.              { Okay, the instruction is syntactically cor-    }
  1675.              { rect.  Now emit the opcode and any necessary    }
  1676.              { operands to memory.                }
  1677.  
  1678.              Val := 0;
  1679.              if (HasOpcode) then  {It's not a blank line }
  1680.              begin
  1681.  
  1682.                  Val := Val or Opcode;
  1683.                 if (HasReg) then Val := Val or Regcode;
  1684.                 if (HasOperand) then Val := Val or OperandCode;
  1685.                 WriteMem(Adrs, Val);
  1686.                 inc(adrs);
  1687.  
  1688.                 if (HasValue) then begin {It has an operand }
  1689.  
  1690.                     WriteMem(Adrs, OperandValue and $ff);
  1691.                         inc(adrs);
  1692.                         WriteMem(Adrs, OperandValue shr 8);
  1693.                         inc (adrs);
  1694.  
  1695.                 end;
  1696.  
  1697.              end;
  1698.  
  1699.          end;
  1700.  
  1701.      end;
  1702.  
  1703.      { Check to see if there were any undefined symbols }
  1704.  
  1705.      for ch := 'A' to 'Z' do
  1706.          if (not SymTbl[ch].Defined)then
  1707.            if (SymTbl[ch].Value <> 0) then
  1708.               ErrorMsg('Undefined Symbol', ch);
  1709.  
  1710. end;
  1711.  
  1712.  
  1713.  
  1714. { Given an opcode, the following function returns the size of    }
  1715. { an instruction (in bytes).  This is either one or three.    }
  1716.  
  1717. function InstrSz(opcode:word):integer;
  1718. begin
  1719.  
  1720.     if (opcode > $1f) or ((opcode and $18) = $10) then
  1721.             if (opcode and $7) >= 5 then Result := 3
  1722.                 else Result := 1
  1723.         else if (opcode and $18) = $8 then Result := 3
  1724.         else Result := 1;
  1725.  
  1726. end;
  1727.  
  1728.  
  1729. { Given an opcode, the following function returns a string that    }
  1730. { corresponds to the instruction's mnemonic.            }
  1731.  
  1732. function Instr(opcode:word):string;
  1733. begin
  1734.  
  1735.         Result := '????';
  1736.     case (opcode shr 5) of
  1737.  
  1738.             1: Result := 'or  ';
  1739.             2: Result := 'and ';
  1740.             3: Result := 'cmp ';
  1741.             4: Result := 'sub ';
  1742.             5: Result := 'add ';
  1743.             6: Result := 'mov ';
  1744.             7: Result := 'mov ';
  1745.             0: begin
  1746.  
  1747.                 if (opcode and $18) = $10 then
  1748.                    Result := 'not '
  1749.                 else if (opcode and $18) = $8 then
  1750.                 begin
  1751.  
  1752.                     case opcode and $7 of
  1753.  
  1754.                     0: Result := 'je  ';
  1755.                     1: Result := 'jne ';
  1756.                     2: Result := 'jb  ';
  1757.                     3: Result := 'jbe ';
  1758.                     4: Result := 'ja  ';
  1759.                     5: Result := 'jae ';
  1760.                     6: Result := 'jmp ';
  1761.                     7: Result := '****';
  1762.                     end;
  1763.  
  1764.                 end
  1765.                 else if (opcode and $18) = $18 then Result := '****'
  1766.                 else begin
  1767.  
  1768.                     case (opcode and $7) of
  1769.                     0: Result := '****';
  1770.                     1: Result := '****';
  1771.                     2: Result := '****';
  1772.                     3: Result := 'brk ';
  1773.                     4: Result := 'iret';
  1774.                     5: Result := 'halt';
  1775.                     6: Result := 'get ';
  1776.                     7: Result := 'put ';
  1777.                     end;
  1778.                 end;
  1779.                end;
  1780.         end;
  1781.  
  1782. end;
  1783.  
  1784.  
  1785.  
  1786. { Given an opcode and an option operand, the following function returns    }
  1787. { a string that represents the reg/memory addressing mode.        }
  1788.  
  1789. function AdrsMode(opcode, operand:word):string;
  1790.  
  1791.     function MemMode(opcode,operand:word):string;
  1792.         begin
  1793.  
  1794.             case opcode and $7 of
  1795.                 0: Result := 'ax';
  1796.                 1: Result := 'bx';
  1797.                 2: Result := 'cx';
  1798.                 3: Result := 'dx';
  1799.                 4: Result := '[bx]';
  1800.                 5: Result := '['+IntToHex(operand,4)+'+bx]';
  1801.                 6: Result := '['+IntToHex(operand,4)+']';
  1802.                 7: Result := IntToHex(operand,4);
  1803.                 end;
  1804.         end;
  1805.  
  1806. begin
  1807.  
  1808.     if (opcode > $1f) or (opcode and $18 = $10) then
  1809.             Result := MemMode(opcode,operand)
  1810.         else if (opcode and $18 = $8) then
  1811.             Result := MemMode($27, operand)
  1812.         else    Result := '';
  1813.  
  1814. end;
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820. { The following function disassembles a single instruction at the given    }
  1821. { address and returns the string representation of that instruction.    }
  1822.  
  1823. function Disassemble2(var CodeAdrs:word):string;
  1824. var     Size,
  1825.     Operand:word;
  1826. begin
  1827.  
  1828.     Result := IntToHex(CodeAdrs,4) + ': ' +
  1829.               IntToHex(ReadMem(CodeAdrs),2) + ' ';
  1830.  
  1831.         Size := InstrSz(ReadMem(CodeAdrs));
  1832.         Opcode := ReadMem(CodeAdrs);
  1833.         if Size = 1 then
  1834.         begin
  1835.  
  1836.             Result := Result + '      ';
  1837.                 inc(CodeAdrs);
  1838.  
  1839.         end
  1840.         else begin
  1841.  
  1842.             Result := Result +
  1843.                    IntToHex(ReadMem(CodeAdrs+1),2) + ' ' +
  1844.                        IntToHex(ReadMem(CodeAdrs+2),2) + ' ';
  1845.                 Operand := ReadMem(CodeAdrs+1) + (ReadMem(CodeAdrs+2) shl 8);
  1846.                 CodeAdrs := CodeAdrs + 3;
  1847.  
  1848.         end;
  1849.         Result := Result + Instr(opcode) + ' ';
  1850.         case (opcode shr 5) of
  1851.         1,2,3,4,5,6:begin
  1852.  
  1853.             case ((opcode shr 3) and $3) of
  1854.                 0: Result := Result + 'ax, ';
  1855.                 1: Result := Result + 'bx, ';
  1856.                 2: Result := Result + 'cx, ';
  1857.                 3: Result := Result + 'dx, ';
  1858.                 end;
  1859.                 Result := Result + AdrsMode(Opcode, Operand);
  1860.             end;
  1861.  
  1862.         7:begin
  1863.  
  1864.             Result := Result + AdrsMode(Opcode, Operand) + ', ';
  1865.                 case ((opcode shr 3) and $3) of
  1866.                 0: Result := Result + 'ax';
  1867.                 1: Result := Result + 'bx';
  1868.                 2: Result := Result + 'cx';
  1869.                 3: Result := Result + 'dx';
  1870.                 end;
  1871.            end;
  1872.  
  1873.         0: begin
  1874.  
  1875.             case (opcode shr 3) and $3 of
  1876.                 1: Result := Result + IntToHex(Operand,4);
  1877.                 2: Result := Result + AdrsMode(Opcode,Operand);
  1878.                 end;
  1879.  
  1880.            end;
  1881.  
  1882.         end;
  1883.  
  1884. end;
  1885.  
  1886.  
  1887.  
  1888. function Disassemble(CodeAdrs:word):string;
  1889. begin
  1890.  
  1891.     Result := Disassemble2(CodeAdrs);
  1892.  
  1893. end;
  1894.  
  1895.  
  1896.  
  1897. { The following event method handles switching between pages on the form. }
  1898.  
  1899. procedure TSIMx86Form.Simx86PagesChange(Sender: TObject;
  1900.                     NewTab: Integer;
  1901.                       var AllowChange: Boolean);
  1902. var DisAdrs:word;
  1903.     i:integer;
  1904. begin
  1905.  
  1906.     { Don't allow a change if a program is running. }
  1907.  
  1908.     if (Running and (NewTab = 0)) then
  1909.         begin
  1910.  
  1911.             AllowChange := false;
  1912.  
  1913.         end
  1914.  
  1915.         { If the user switches to the memory page, redraw all the cells. }
  1916.  
  1917.     else if (NewTab = 1) then
  1918.             AdrsEntryChange(AdrsEntry)
  1919.  
  1920.         { If the user switches to the execute page, disassemble some    }
  1921.         { code for the disassembly list box.                }
  1922.  
  1923.         else if (NewTab = 2) then
  1924.         begin
  1925.  
  1926.             DisAdrs := HexToWord(DisAsmAdrs.Text);
  1927.             DisAsm.Clear;
  1928.             for i := 1 to 15 do
  1929.                 DisAsm.Items.Add(Disassemble2(DisAdrs));
  1930.             Instruction.Caption := Disassemble(IP);
  1931.  
  1932.         end;
  1933.  
  1934. end;
  1935.  
  1936.  
  1937.  
  1938. { If the user changes the address in the TEdit box at the bottom of the    }
  1939. { disassembly list box, the following procedure converts this to a word    }
  1940. { and disassembles 15 instructions starting at this new address.    }
  1941.  
  1942. procedure TSIMx86Form.DisAsmAdrsChange(Sender: TObject);
  1943. var i:integer;
  1944.     DisAdrs:word;
  1945. begin
  1946.  
  1947.     DisAdrs := HexToWord(DisAsmAdrs.Text);
  1948.     DisAsm.Clear;
  1949.     for i := 1 to 15 do
  1950.         DisAsm.Items.Add(Disassemble2(DisAdrs));
  1951.  
  1952. end;
  1953.  
  1954.  
  1955. { If the user presses on the down portion of the spinner at the bottom    }
  1956. { of the disassembly list box, this method increments the disassembly    }
  1957. { address and updates the disassembly list box.                }
  1958.  
  1959. procedure TSIMx86Form.SpinButtonDownClick(Sender: TObject);
  1960. var value:word;
  1961. begin
  1962.  
  1963.     Value := HexToWord(DisAsmAdrs.Text);
  1964.     inc(Value);
  1965.     DisAsmAdrs.Text := IntToHex(Value,4);
  1966.  
  1967. end;
  1968.  
  1969. { If they press on the up arrow portion of the spinner, this code will    }
  1970. { decrement the starting disassembly address and update the list box.    }
  1971.  
  1972. procedure TSIMx86Form.SpinButtonUpClick(Sender: TObject);
  1973. var value:word;
  1974. begin
  1975.  
  1976.     Value := HexToWord(DisAsmAdrs.Text);
  1977.     dec(Value);
  1978.     DisAsmAdrs.Text := IntToHex(Value,4);
  1979.  
  1980. end;
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989. procedure OneInstr;
  1990.  
  1991.  
  1992.     procedure Store(mode:byte; index:word; value: word);
  1993.     begin
  1994.  
  1995.     case mode of
  1996.  
  1997.         0: AX := value;
  1998.         1: BX := value;
  1999.         2: CX := value;
  2000.         3: DX := value;
  2001.         4: begin
  2002.  
  2003.             WriteMem(bx, value and $FF);
  2004.                 WriteMem(bx+1, value shr 8);
  2005.  
  2006.            end;
  2007.  
  2008.         5: begin
  2009.  
  2010.             WriteMem(bx+index, value and $FF);
  2011.                 WriteMem(bx+index+1, value shr 8);
  2012.  
  2013.            end;
  2014.  
  2015.         6: begin
  2016.  
  2017.             WriteMem(index, value and $FF);
  2018.                 WriteMem(index+1, value shr 8);
  2019.  
  2020.            end;
  2021.  
  2022.         end;
  2023.  
  2024.     end;
  2025.  
  2026.  
  2027. begin
  2028.  
  2029.     with  SIMx86Form do begin
  2030.  
  2031.                 if (PendingInt) and (not InInt) then
  2032.                    if (IntAdrs <> $FFFF) then
  2033.                    begin
  2034.  
  2035.                        InInt := true;
  2036.                         SaveAX := AX;
  2037.                         SaveBX := BX;
  2038.                         SaveCX := CX;
  2039.                         SaveDX := DX;
  2040.                         SaveIP := IP;
  2041.                         SaveLess := LessThanFlag.Checked;
  2042.                         SaveEqual:= EqualFlag.Checked;
  2043.                         PendingInt := false;
  2044.  
  2045.                         IP := IntAdrs;
  2046.  
  2047.                    end;
  2048.  
  2049.                 { Okay, do the instruction here.    }
  2050.  
  2051.                 Opcode := ReadMem(IP);
  2052.                 Operation := Opcode shr 5;
  2053.                 Reg := (Opcode shr 3) and $3;
  2054.                 RegMem := Opcode and $7;
  2055.                 InstrSize := 1;
  2056.  
  2057.                 case Reg of
  2058.                   0: Op1 := @AX;
  2059.                   1: Op1 := @BX;
  2060.                   2: Op1 := @CX;
  2061.                   3: Op1 := @DX;
  2062.                 end;
  2063.  
  2064.  
  2065.                 case RegMem of
  2066.                   0: Op2v := AX;
  2067.                   1: Op2v := BX;
  2068.                   2: Op2v := CX;
  2069.                   3: Op2v := DX;
  2070.  
  2071.                   4: Op2v := ReadMem(BX) + (ReadMem(BX+1) shl 8);
  2072.  
  2073.                   5: begin {[1000+bx]}
  2074.  
  2075.                       offset := BX + ReadMem(IP+1) + ReadMem(IP+2) shl 8;
  2076.                       Op2v := ReadMem(offset) + ReadMem(offset+1) shl 8;
  2077.                         InstrSize := 3;
  2078.  
  2079.                      end;
  2080.  
  2081.                   6: begin {[1000]}
  2082.  
  2083.                       offset := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
  2084.                       Op2v := ReadMem(offset) + ReadMem(offset+1) shl 8;
  2085.                         InstrSize := 3;
  2086.  
  2087.                      end;
  2088.  
  2089.                   7: begin {1000}
  2090.  
  2091.                       Op2v := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
  2092.                         InstrSize := 3;
  2093.  
  2094.                      end;
  2095.  
  2096.                 end;
  2097.  
  2098.                 case Operation of
  2099.  
  2100.                   1: Op1^ := Op1^ or Op2v;
  2101.           2: Op1^ := Op1^ and Op2v;
  2102.  
  2103.                   3: begin
  2104.  
  2105.                       LessThanFlag.Checked := Op1^ < Op2v;
  2106.                         EqualFlag.Checked := Op1^ = Op2v;
  2107.  
  2108.                      end;
  2109.  
  2110.           4: Op1^ := Op1^ - Op2v;
  2111.           5: Op1^ := Op1^ + Op2v;
  2112.                   6: Op1^ := Op2v;
  2113.                   7: Store(regmem, ReadMem(IP+1) + ReadMem(IP+2) shl 8, Op1^);
  2114.  
  2115.                   0: case Reg of
  2116.  
  2117.                       2: Store(regmem,
  2118.                              ReadMem(IP+1) + ReadMem(IP+2) shl 8,
  2119.                                  not Op2v);
  2120.  
  2121.                         1: begin {jumps}
  2122.  
  2123.                             InstrSize := 0;
  2124.                             case RegMem of
  2125.  
  2126.                             0: if EqualFlag.Checked then
  2127.                                     IP := ReadMem(IP+1) +
  2128.                                             ReadMem(IP+2) shl 8
  2129.                                    else InstrSize := 3;
  2130.  
  2131.                             1: if not EqualFlag.Checked then
  2132.                                     IP := ReadMem(IP+1) +
  2133.                                             ReadMem(IP+2) shl 8
  2134.                                    else InstrSize := 3;
  2135.  
  2136.                             2: if LessThanFlag.Checked then
  2137.                                     IP := ReadMem(IP+1) +
  2138.                                             ReadMem(IP+2) shl 8
  2139.                                    else InstrSize := 3;
  2140.  
  2141.                             3: if LessThanFlag.Checked or
  2142.                                       EqualFlag.Checked then
  2143.                                     IP := ReadMem(IP+1) +
  2144.                                             ReadMem(IP+2) shl 8
  2145.                                    else InstrSize := 3;
  2146.  
  2147.                             4: if not (LessThanFlag.Checked or
  2148.                                            EqualFlag.Checked) then
  2149.                                     IP := ReadMem(IP+1) +
  2150.                                             ReadMem(IP+2) shl 8
  2151.                                    else InstrSize := 3;
  2152.  
  2153.                             5: if not LessThanFlag.Checked then
  2154.                                     IP := ReadMem(IP+1) +
  2155.                                             ReadMem(IP+2) shl 8
  2156.                                    else InstrSize := 3;
  2157.  
  2158.                             6: IP := ReadMem(IP+1) + ReadMem(IP+2) shl 8;
  2159.  
  2160.                                 7: begin
  2161.  
  2162.                                     ErrorMsg('Illegal instruction',
  2163.                                              IntToHex(IP,4));
  2164.  
  2165.                                         Halted := true;
  2166.  
  2167.                                    end;
  2168.  
  2169.                                 end;
  2170.                            end;
  2171.  
  2172.                         3: begin
  2173.  
  2174.                             ErrorMsg('Illegal instruction',IntToHex(IP,4));
  2175.                 Halted := true;
  2176.  
  2177.                            end;
  2178.  
  2179.                         0: case (RegMem) of
  2180.                            0,1,2:begin
  2181.  
  2182.                             ErrorMsg('Illegal instruction',IntToHex(IP,4));
  2183.                 Halted := true;
  2184.                                 InstrSize := 0;
  2185.  
  2186.                               end;
  2187.  
  2188.                            3: begin
  2189.  
  2190.                             ErrorMsg('BRK encountered',IntToHex(IP,4));
  2191.                 Halted := true;
  2192.                                 InstrSize := 1;
  2193.  
  2194.                               end;
  2195.  
  2196.                            4: if (not InInt) then
  2197.                               begin
  2198.  
  2199.                             ErrorMsg('IRET encountered outside interrupt',
  2200.                                      IntToHex(IP,4));
  2201.                 Halted := true;
  2202.                                 InstrSize := 0;
  2203.  
  2204.                               end
  2205.                               else begin
  2206.  
  2207.                                   AX := SaveAX;
  2208.                                   BX := SaveBX;
  2209.                                   CX := SaveCX;
  2210.                                   DX := SaveDX;
  2211.                                   IP := SaveIP;
  2212.                                 LessThanFlag.Checked := SaveLess;
  2213.                                 EqualFlag.Checked := SaveEqual;
  2214.                                 InstrSize := 0;
  2215.                                 InInt := false;
  2216.  
  2217.                               end;
  2218.  
  2219.                            5: begin
  2220.  
  2221.                             ErrorMsg('Halt encountered',IntToHex(IP,4));
  2222.                 Halted := true;
  2223.                                 InstrSize := 0;
  2224.  
  2225.                               end;
  2226.  
  2227.                            6: begin
  2228.  
  2229.                                InputForm.ShowModal;
  2230.                                AX := InputValue;
  2231.                                 InstrSize := 1;
  2232.  
  2233.                               end;
  2234.  
  2235.                            7: begin
  2236.  
  2237.                                Output.Items.Add(IntToHex(AX,4));
  2238.                                 InstrSize := 1;
  2239.  
  2240.                               end;
  2241.  
  2242.                         end;
  2243.                   end;
  2244.                 end;
  2245.                 IP := IP + InstrSize;
  2246.  
  2247.         end;
  2248.  
  2249. end;
  2250.  
  2251.  
  2252. procedure StopPgm;
  2253. begin
  2254.  
  2255.     with SIMx86Form do begin
  2256.  
  2257.     IPValue.Enabled := true;
  2258.     DisAsmAdrs.Enabled := true;
  2259.     SpinButton.Enabled := true;
  2260.     RunBtn.Enabled := true;
  2261.     StepBtn.Enabled := true;
  2262.     AXValue.Enabled := true;
  2263.     BXValue.Enabled := true;
  2264.     CXValue.Enabled := true;
  2265.     DXValue.Enabled := true;
  2266.     LessThanFlag.Enabled := true;
  2267.     EqualFlag.Enabled := true;
  2268.     HaltBtn.Enabled := false;
  2269.         RunningLite.Color := clGray;
  2270.         MainMenu.Items[0].Enabled := true;
  2271.         MainMenu.Items[1].Enabled := true;
  2272.         PendingInt := false;
  2273.         Instruction.Caption := Disassemble(IP);
  2274.  
  2275.     end;
  2276.  
  2277. end;
  2278.  
  2279. { If the users presses the "RUN" button, the following code kicks in    }
  2280. { the emulator.                                }
  2281.  
  2282. procedure TSIMx86Form.RunBtnClick(Sender: TObject);
  2283.  
  2284.  
  2285. begin
  2286.  
  2287.     IPValue.Enabled := false;
  2288.     DisAsmAdrs.Enabled := false;
  2289.     SpinButton.Enabled := false;
  2290.     RunBtn.Enabled := false;
  2291.     StepBtn.Enabled := false;
  2292.     AXValue.Enabled := false;
  2293.     BXValue.Enabled := false;
  2294.     CXValue.Enabled := false;
  2295.     DXValue.Enabled := false;
  2296.     LessThanFlag.Enabled := false;
  2297.     EqualFlag.Enabled := false;
  2298.     HaltBtn.Enabled := true;
  2299.         RunningLite.Color := clRed;
  2300.         PendingInt := false;
  2301.  
  2302.         MainMenu.Items[0].Enabled := false;
  2303.         MainMenu.Items[1].Enabled := false;
  2304.  
  2305.         Halted := false;
  2306.         Running := true;
  2307.         InInt := false;
  2308.  
  2309.  
  2310.  
  2311.         while not Halted do begin
  2312.  
  2313.             Application.ProcessMessages;
  2314.                 OneInstr;
  2315.  
  2316.         end;
  2317.         Running := false;
  2318.         RunningLite.Color := clGray;
  2319.         StopPgm;
  2320.  
  2321.         IPValue.Text := IntToHex(IP,4);
  2322.         AXValue.Text := IntToHex(AX,4);
  2323.         BXValue.Text := IntToHex(BX,4);
  2324.         CXValue.Text := IntToHex(CX,4);
  2325.         DXValue.Text := IntToHex(DX,4);
  2326.  
  2327. end;
  2328.  
  2329. procedure TSIMx86Form.HaltBtnClick(Sender: TObject);
  2330. begin
  2331.  
  2332.     StopPgm;
  2333.         Halted := true;
  2334.  
  2335. end;
  2336.  
  2337.  
  2338. { If the user presses the reset button, the following method resets    }
  2339. { the machine.                                }
  2340.  
  2341. procedure TSIMx86Form.ResetBtnClick(Sender: TObject);
  2342. begin
  2343.  
  2344.     AX := 0;
  2345.         BX := 0;
  2346.         CX := 0;
  2347.         DX := 0;
  2348.         AXValue.Text := '0000';
  2349.         BXValue.Text := '0000';
  2350.         CXValue.Text := '0000';
  2351.         DXValue.Text := '0000';
  2352.         if (ResetVect.Color <> clRed) then
  2353.         begin
  2354.  
  2355.             IP := HexToWord(ResetVect.Text);
  2356.             IPValue.Text := ResetVect.Text;
  2357.  
  2358.         end
  2359.         else begin
  2360.  
  2361.             IP := 0;
  2362.                 IPValue.Text := '0000';
  2363.  
  2364.         end;
  2365.         LessThanFlag.Checked := false;
  2366.         EqualFlag.Checked := false;
  2367.         PendingInt := false;
  2368.         StopPgm;
  2369.         Halted := true;
  2370.         Output.Items.Clear;
  2371.         Input.Items.Clear;
  2372.         Instruction.Caption := Disassemble(IP);
  2373.  
  2374.  
  2375. end;
  2376.  
  2377.  
  2378.  
  2379.  
  2380. procedure TSIMx86Form.InterruptBtnClick(Sender: TObject);
  2381. begin
  2382.  
  2383.     PendingInt := true;
  2384.  
  2385. end;
  2386.  
  2387.  
  2388.  
  2389. procedure TSIMx86Form.IntVectChange(Sender: TObject);
  2390. begin
  2391.  
  2392.     CheckHex(IntVect);
  2393.         if (IntVect.Color <> clRed) then
  2394.         begin
  2395.  
  2396.             IntAdrs := HexToWord(IntVect.Text);
  2397.  
  2398.         end;
  2399. end;
  2400.  
  2401. procedure TSIMx86Form.IPValueChange(Sender: TObject);
  2402. begin
  2403.  
  2404.     CheckHex(IPValue);
  2405.         if IPValue.Color <> clRed then
  2406.         begin
  2407.  
  2408.             IP := HexToWord(IPValue.Text);
  2409.  
  2410.         end;
  2411.         Instruction.Caption := Disassemble(IP);
  2412.  
  2413. end;
  2414.  
  2415. procedure TSIMx86Form.StepBtnClick(Sender: TObject);
  2416. begin
  2417.  
  2418.     OneInstr;
  2419.         IPValue.Text := IntToHex(IP,4);
  2420.         AXValue.Text := IntToHex(AX,4);
  2421.         BXValue.Text := IntToHex(BX,4);
  2422.         CXValue.Text := IntToHex(CX,4);
  2423.         DXValue.Text := IntToHex(DX,4);
  2424.         Instruction.Caption := Disassemble(IP);
  2425.  
  2426. end;
  2427.  
  2428.  
  2429. end.
  2430.  
  2431.